﻿#include "../lib/src/basic/CClientListenerModule.h"
#include "../lib/src/game/CClientMainModule.h"
#include "../lib/src/game/CClientViewModule.h"

#include "GameView.h"
#include "../lib/src/game/MsgID.h"
#include "../lib/src/game/MsgStruct.h"
#include "../lib/src/game/MiscDefine.h"

#include <windows.h>

#pragma comment(lib, "../Debug/ComLib.lib")

#pragma comment(lib,"WSOCK32.LIB")
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)

static char _log_buf[1024] = { 0 };

#define CLINET_DEBUG_LOG(fmt, ...) { \
	memset(_log_buf, 0, sizeof(_log_buf)); \
	sprintf(_log_buf, "%s:%d fn:%s " fmt "\n", strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \
	WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), _log_buf, strlen(_log_buf), NULL, NULL); \
}

bool keys[256] = {0};
int	 mCloseButtonState;
LRESULT WINAPI WndPro(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);

HWND startHwnd;
CGameView mpGameView;
CClientMainModule clientModuleMain;
CClientListenerModule client_listener;
CClientViewModule viewModule;

extern "C" {
	int hide_ready_btn() {
		::ShowWindow(startHwnd, SW_HIDE);
		return 0;
	}

	int refresh_all_atoms_tmp(ST_NOTIFY_VIEW_ATOMS_CHANGED* c) {
		mpGameView.refreshAtom(c);
		return 0;
	}
}

int init_module() {
	AllocConsole();
	construct_client_view(&viewModule, "client view module");
	construct_client_main(&clientModuleMain, "client main");
	clientModuleMain.view = AS_MODULE(&viewModule);

	construct_client_listener(&client_listener, "client listener", "127.0.0.1", 5161, AS_MODULE(&clientModuleMain));
	client_listener.connect_server(&client_listener);
	return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	init_module();

	WNDCLASS wc;
	ZeroMemory(&wc,sizeof(wc));
	wc.hbrBackground = HBRUSH(COLOR_WINDOW+1);
	wc.hCursor = LoadCursor(NULL,IDC_ARROW);
	wc.hIcon = LoadIcon(NULL,IDI_QUESTION);
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndPro;
	wc.lpszClassName = "totris";
	wc.lpszMenuName = NULL;
	wc.style=CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
	RegisterClass(&wc);

	int cxScreen=GetSystemMetrics(SM_CXSCREEN);
	int cyScreen=GetSystemMetrics(SM_CYSCREEN);

	HWND hWnd_Main=CreateWindowEx(WS_EX_LAYERED, "totris", NULL, WS_POPUP | WS_VISIBLE, (cxScreen-SCREEN_WIDTH) >> 1, (cyScreen - SCREEN_HEIGHT) >> 1, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL);
	SetLayeredWindowAttributes(hWnd_Main, RGB(255, 0, 255), 0, LWA_COLORKEY);

	mpGameView.mHwnd = hWnd_Main;
	mpGameView.initDC();
	startHwnd = CreateWindowEx(0, "button", "start", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 150, 150, 50, 20, hWnd_Main, (HMENU)IDB_START_GAME, hInstance, NULL);
	
	ShowWindow(hWnd_Main, SW_SHOW);
	UpdateWindow(hWnd_Main);
	mpGameView.reDraw();

	CLINET_DEBUG_LOG("win32 loop msg start.");
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

int on_key_down(unsigned int key) {
	ST_NOTIFY_KEY_DOWN k = {{MSG_ID_NOTIFY_KEY_DOWN, sizeof(k) - sizeof(CMsg)}, 0};
	switch (key) {
	case VK_UP:
	case VK_LEFT:
	case VK_RIGHT:
	case VK_DOWN:
		CLINET_DEBUG_LOG("key pressed key=%d.", key);
		k.key = key;
		AS_MODULE(&clientModuleMain)->sendMsg(AS_MODULE(&clientModuleMain), &k.msg);
		break;
	case VK_HOME:
		break;
	case VK_CONTROL:
		break;
	default:
		break;
	}
	return 0;
}

LRESULT WINAPI WndPro(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) {
	PAINTSTRUCT ps;
	HDC hdc;
	int i = 0;
	static int winWidth = 0, winHeight = 0;
	
	static RECT rt_Close[3];
	POINT pt_Mouse;
	RECT rt_ChuangKouQu;
	static BOOL bWinMaxsize;
	static BOOL bMoveWinFlag;
	static POINT pt_MouseMove_Old;
	static POINT pt_MouseMove_New;

	RECT winRect;
	POINT pt = {100, 100};
	CModule* clinet_main = AS_MODULE(&clientModuleMain);

	switch(msg) {
	case WM_SIZE:
		winWidth = LOWORD(lParam);
		winHeight = HIWORD(lParam);
		GetClientRect(hWnd, &winRect);
		for (i=0;i<3;i++) {
			SetRect(&rt_Close[i], winWidth - 22 - 15 - i * 20, 2, winWidth - 15 - i * 20 , 14);
		}
		break;
	case WM_LBUTTONDBLCLK:
		PostMessage(hWnd,WM_SYSCOMMAND,bWinMaxsize?SC_RESTORE:SC_MAXIMIZE,0);
		bWinMaxsize ^= 1;
		break;
	case WM_MOUSEMOVE:
		if(bMoveWinFlag) {
			GetCursorPos(&pt_MouseMove_New);
			GetWindowRect(hWnd,&rt_ChuangKouQu);
			MoveWindow(hWnd,rt_ChuangKouQu.left+pt_MouseMove_New.x-pt_MouseMove_Old.x,
				rt_ChuangKouQu.top+pt_MouseMove_New.y-pt_MouseMove_Old.y,
				rt_ChuangKouQu.right-rt_ChuangKouQu.left,
				rt_ChuangKouQu.bottom-rt_ChuangKouQu.top,TRUE);
			pt_MouseMove_Old=pt_MouseMove_New;
		}

		pt_Mouse.x = LOWORD(lParam);
		pt_Mouse.y = HIWORD(lParam);
		for (i = 0;i < 3; i++) {
			if(PtInRect(&rt_Close[i],pt_Mouse)) {
				break;    
			}			
		}

		GetClientRect(hWnd, &winRect);
		if (0 == i) {
			mCloseButtonState = 1;
			InvalidateRect(hWnd, &winRect, 0);
		} else if (0 != mCloseButtonState) {
			mCloseButtonState = 0;
			InvalidateRect(hWnd, &winRect, 0);
		}
		break;
	case WM_LBUTTONDOWN:
		pt_Mouse.x=LOWORD(lParam);
		pt_Mouse.y=HIWORD(lParam);
		for (i=0;i<3;i++) {
			if(PtInRect(&rt_Close[i], pt_Mouse)) {
				break;
			}
		}
		if(i < 3) {
			switch(i) {
			case 0:
				PostMessage(hWnd,WM_SYSCOMMAND,SC_CLOSE,0);
				break;
			case 1:
				PostMessage(hWnd,WM_SYSCOMMAND,bWinMaxsize?SC_RESTORE:SC_MAXIMIZE,0);bWinMaxsize^=1;
				break;
			case 2:
				PostMessage(hWnd,WM_SYSCOMMAND,SC_MINIMIZE,0);
				break;
			}
		} else {            
			bMoveWinFlag=1;
			SetCapture(hWnd);
			GetCursorPos(&pt_MouseMove_Old);
		}
		break;
	case WM_LBUTTONUP:
		bMoveWinFlag=0;
		ReleaseCapture();
		break;

	case WM_KEYDOWN:
		keys[wParam] = true;
		on_key_down(wParam);
		break;
	case WM_KEYUP:
		keys[wParam] = false;
		break;
	case WM_PAINT:
		hdc=BeginPaint(hWnd, &ps);
		mpGameView.onPaint();
		EndPaint(hWnd,&ps);
		break;
	case WM_COMMAND:
		if (wParam == IDB_START_GAME) {
			CMsg msg = {MSG_ID_PREPARE_READY, 0};
			clinet_main->sendMsg(clinet_main, &msg);
		}
		break;
	case WM_TIMER:
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, msg, wParam, lParam);    
	}
	return 0;
}